package marks

import (
	"errors"
	"fmt"
	"github.com/boltdb/bolt"
)

// 增删改查

var DB_Path = "./db/hash.db"

type DB struct {
	Db *bolt.DB
}

func NewDB(path string) *DB {
	db, e := bolt.Open(path, 0600, nil)

	if e != nil {
		panic(e)
	}

	return &DB{
		Db: db,
	}
}

var DbName = "bash.db"



func (this *DB)Add(bucketName, key, value []byte) error {

	//添加之前检查是否已经存在相同的CID，若存在返回失败信息

	var err error
	if key == nil || value == nil {
		err = errors.New("key or value can not empty ")
	} else {
		err = this.Db.Update(func(tx *bolt.Tx) error {
			bucket := tx.Bucket(bucketName)
			if bucket == nil {
				newBucket, e := tx.CreateBucket(bucketName)
				if e != nil {
					fmt.Println("create a table named of",string(bucketName)+"failed")
					return e
				}
				bucket = newBucket
			}

			res := bucket.Get(key)
			if res != nil{
				return errors.New("this object exist already don't add again")
			}
			err = bucket.Put(key, value)
			if err != nil {
				return err
			}
			err = bucket.Put([]byte(LastKey), value)
			if err != nil {
				fmt.Println("hash update failed")
			}else {
				fmt.Println("hash update succeeded")
			}
			return err
		})
	}

	return err
}

func (this *DB)Update(bucketName, key, value []byte) error {
	var err error
	err = this.Db.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(bucketName)
		if bucket != nil {
			err = bucket.Put(key, value)
			if err != nil {
				return err
			}
			bucket.Put([]byte(LastKey),value)
		} else {
			return errors.New(fmt.Sprintf("%s not exist", string(bucketName)))
		}
		return err
	})

	return err
}

func (this *DB)View(bucketName, key []byte) ([]byte, error) {
	var result []byte
	err := this.Db.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(bucketName)
		if bucket != nil {
			res := bucket.Get(key)
			if res != nil {
				result = res
				return nil
			} else {
				return errors.New(fmt.Sprintf("%s not exist", string(key)))
			}
		} else {
			return errors.New(fmt.Sprintf("%s not exist", string(bucketName)))
		}
	})

	return result, err

}

func (this *DB)Delete(bucketName, key []byte) bool {
	err := this.Db.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(bucketName)
		if bucket != nil{
			err := bucket.Delete(key)
			if err != nil{
				return errors.New(fmt.Sprintf("%s not exist,delete faild", string(key)))
			}else {
				return nil
			}
		} else {
			return errors.New(fmt.Sprintf("%s not exist", string(bucketName)))
		}
	})
	if err != nil{
		return false
	}

	return true
}
